Skip to main content

Laravel 服务容器粗浅认知

简介

在讲解 服务容器 的初始化前,我们先要弄明白 服务容器 到底是个什么东东。

从数据类型本质上来说,Laravel 服务容器就是一个类,PHP 解析过程会被实例化为一个对象。我们都知道 PHP 实例化类要调用类的构造方法的,而这个执行构造方法的过程就是 服务容器的初始化

从程序设计原则上看,Laravel 服务容器就是我们经常听到的 IoC/DI 容器,而且还是一个高级 IoC/DI 容器。

从程序设计模式上看,Laravel 服务容器可以看成 一棵树,一颗注册树。

IoC/DI 容器

IoC: Inversion of Control -- 控制反转

DI: Dependency Injection -- 依赖注入

控制反转、依赖注入,呵呵,多么高深、逼格高的两个词语。不得不吐槽,这种掩盖本质特征,给人一头雾水的词语,我真心不喜欢。当然我这是从初学者角度去看问题的,如果从创造这两个词语的大神角度去看,他该吐槽我了。

好了,简要讲明这两个词的含义:

控制反转是相对于控制正转来讲的,有反必有正。有光明必有黑暗,抛弃黑暗讲光明,就像抛弃女人讲男人,那还叫男人吗,应该叫大写的G,哈哈开个玩笑。

依赖注入是控制反转的另一面的说法,说的都是同一种现象。就如同:有人给我送礼物。对于我来说,是拿礼物;而对于他来说,是送礼物。本质上都在讲礼物一个传递过程。而控制反转就是拿礼物,依赖注入就是送礼物。

控制正转

class A
{
protected $b;

public function __construct()
{
$this->b = new B();
}

public function getB()
{
return $this->b;
}
}

class B
{
public function __construct(){}
}

$b = (new A)->getB();
var_dump($b);

上面,不难看出 new A 需要 new B。这种主动 new B 的现象就叫做控制正转

控制反转

class A
{
protected $ioc;

public function __construct(Ioc $ioc)
{
$this->ioc = $ioc;
}

public function getB()
{
return $this->ioc->make('b');
}
}

class Ioc
{
protected $instances = [];

public function __construct()
{
$this->instances['a'] = new A($this);
$this->instances['b'] = new B($this);
}

public function make(string $abstract)
{
return $this->instances[$abstract];
}
}

class B
{
protected $ioc;

public function __construct(Ioc $ioc)
{
$this->ioc = $ioc;
}
}

$ioc = new Ioc();
$a = $ioc->make('a');
$b = $a->getB();
var_dump($b);

如同上面这样,不需要在 A 中直接 new B。而是让 IoC 容器将 B 给我,这就叫控制反转。

依赖注入

控制反转是站在 A 的立场来看的,它是拿 B 的。

依赖注入是站在 IoC 的立场来看的,它是送 B 的。

注册树模式

Laravel 服务容器抽象点讲,如下打了一比方:

注册树模式不好形容,我们把这颗树换成一个大箱子。所有提供服务的实例对象,是这个大箱子里面的物品。且在 Laravel 中会对大箱子里面的物品进行分类。没做好的物品放到一类,并做好复杂标记;做好的物品放到一类,并做好唯一标记。

而当我们要使用没有做好的物品时,会对这个物品做最后加工,确保能用,才给我们用,并且把这个做好的归类到做好一类中,并把原先的复杂标记删掉。

当我们要是用做好的物品时,大箱子会直接给我们用。